package com.bingxue.edu.framework.common.model;

import cn.hutool.core.bean.BeanUtil;
import com.mybatisflex.core.paginate.Page;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * @author panbo
 * @since 2024/6/26
 */
@Data
@Accessors(chain = true)
public class Pagination<T> {

    @Schema(title = "当前页")
    private int page;

    @Schema(title = "每页数量")
    private int size;

    @Schema(title = "总数")
    private long total;

    @Schema(title = "数据")
    private Collection<T> records = Collections.emptyList();

    /**
     * 基于 MyBatis Flex 分页数据构建分页信息
     *
     * @param page        MyBatis Plus 分页数据
     * @param <T>         源列表数据类型
     * @return 分页信息
     */
    public static <T> Pagination<T> of(Page<T> page) {
        Pagination<T> pagination = ofEmpty();
        pagination.setRecords(page.getRecords());
        pagination.setPage((int) page.getPageNumber());
        pagination.setSize((int) page.getPageSize());
        pagination.setTotal(page.getTotalRow());
        return pagination;
    }

    /**
     * 基于 MyBatis Flex 分页数据构建分页信息，并将源数据转换为指定类型数据
     *
     * @param page        MyBatis Plus 分页数据
     * @param targetClass 目标类型 Class 对象
     * @param <T>         源列表数据类型
     * @param <VO>         目标列表数据类型
     * @return 分页信息
     */
    public static <T, VO> Pagination<VO> of(Page<T> page, Class<VO> targetClass) {
        Pagination<VO> pagination = ofEmpty();
        if (page == null) {
            return pagination;
        }
        pagination.setRecords(BeanUtil.copyToList(page.getRecords(), targetClass));
        pagination.setPage((int) page.getPageNumber());
        pagination.setSize((int) page.getPageSize());
        pagination.setTotal(page.getTotalRow());
        return pagination;
    }

    /**
     * 基于列表数据构建分页信息
     *
     * @param page 页码
     * @param size 每页条数
     * @param list 列表数据
     * @param <VO>  列表数据类型
     * @return 分页信息
     */
    public static <VO> Pagination<VO> of(int page, int size, List<VO> list) {
        Pagination<VO> pagination = ofEmpty();
        if (list == null) {
            return pagination;
        }
        Pagination<VO> pageResp = new Pagination<>();
        pageResp.setTotal(list.size());
        // 对列表数据进行分页
        int fromIndex = (page - 1) * size;
        int toIndex = page * size + fromIndex;
        if (fromIndex > list.size()) {
            pageResp.setRecords(new ArrayList<>(0));
        } else if (toIndex >= list.size()) {
            pageResp.setRecords(list.subList(fromIndex, list.size()));
        } else {
            pageResp.setRecords(list.subList(fromIndex, toIndex));
        }
        return pageResp;
    }

    private static <VO> Pagination<VO> ofEmpty() {
        return new Pagination<>();
    }

}
